import { error, fail, redirect } from '@sveltejs/kit'; import { db } from '$lib/server/db'; import { groceries, categories } from '$lib/server/db/schema'; import { eq } from 'drizzle-orm'; import { categoriesService, groceriesService, referencesService, } from '$lib/server/services'; import { idAction } from '$lib/server/services/grocery-actions'; import { numericId, parseFormString, parseOptionalNumber, } from '$lib/server/services/validation'; import { isUniqueViolation } from '$lib/server/db/errors'; import type { Category, Grocery, Reference } from '$lib/server/services/types'; import type { Actions, PageServerLoad } from './$types'; export interface GroceryDetailOutput { item: Grocery & { categoryName: string | null }; references: Reference[]; categories: Category[]; } export const load: PageServerLoad = async ({ params, url }) => { const id = numericId(params.id); const [item] = await db.select().from(groceries).where(eq(groceries.id, id)); if (!item) throw error(404, 'Article introuvable'); const [cat] = item.categoryId ? await db .select() .from(categories) .where(eq(categories.id, item.categoryId)) : [null]; const refs = await referencesService.loadForGrocery(id); const cats = await categoriesService.loadAll(); const from = url.searchParams.get('from') || '/'; return { item: { ...item, categoryName: cat?.name ?? null, }, references: refs, categories: cats, from, }; }; export const actions: Actions = { add: async ({ request, params }) => { const data = await request.formData(); const groceryId = numericId(params.id); const reference = parseFormString(data.get('reference')); const price = parseOptionalNumber(data.get('price')); const unit = parseFormString(data.get('unit')); const qualityScore = parseOptionalNumber(data.get('quality_score')); if (!reference) { return fail(400, { error: 'La référence est requise' }); } await referencesService.add( groceryId, reference, price, unit, qualityScore, ); return { success: true, type: 'add' as const }; }, delete: ({ request }) => idAction(request, (id) => referencesService.deleteReference(id), { type: 'delete', }), promote: ({ request }) => idAction(request, (id) => referencesService.promote(id), { type: 'promote', }), update: async ({ request, params }) => { const data = await request.formData(); const groceryId = numericId(params.id); const name = parseFormString(data.get('name')); const rawCategoryId = parseOptionalNumber(data.get('category_id')); const categoryId = rawCategoryId === -1 ? null : rawCategoryId; if (!name) { return fail(400, { error: 'Le nom est requis' }); } try { await groceriesService.updateGrocery(groceryId, name, categoryId); } catch (error) { if (isUniqueViolation(error)) { return fail(400, { error: 'Un article porte déjà ce nom' }); } throw error; } return { success: true, type: 'update' as const }; }, deleteItem: async ({ params, request }) => { const groceryId = numericId(params.id); await groceriesService.deleteGrocery(groceryId); const data = await request.formData(); const from = parseFormString(data.get('from')) || '/'; throw redirect(303, from); }, };